package client

import (
	"fmt"
	"net"

	"go.uber.org/zap"

	"go-war3proxy/pkg/const"
)

// LocalWar3GameBroadcast 监听本地war3 game的6112端口的UDP广播数据包
type LocalWar3GameBroadcast struct {
	client *Client
	logger *zap.Logger
	conn   net.PacketConn
	closed bool
}

// NewLocalWar3GameBroadcast 创建新的本地广播监听器
func NewLocalWar3GameBroadcast(client *Client, logger *zap.Logger) *LocalWar3GameBroadcast {
	return &LocalWar3GameBroadcast{
		client: client,
		logger: logger.With(zap.String("component", "local_broadcast")),
	}
}

// Start 启动本地广播监听
func (lwgb *LocalWar3GameBroadcast) Start() error {
	// 监听War3端口，接收本地War3游戏的UDP广播
	// 必须监听在本地IP上，这样才能接收到War3游戏发送的UDP包
	address := fmt.Sprintf("%s:%d", lwgb.client.GetWar3LocalIP(), consts.War3Port)

	lwgb.logger.Info("启动本地War3游戏UDP广播监听", zap.String("address", address))

	conn, err := net.ListenPacket("udp", address)
	if err != nil {
		return fmt.Errorf("UDP监听失败: %w", err)
	}

	// 设置为广播模式
	if udpConn, ok := conn.(*net.UDPConn); ok {
		if err := udpConn.SetReadBuffer(1024 * 1024); err != nil {
			lwgb.logger.Warn("设置UDP读缓冲区失败", zap.Error(err))
		}
	}

	lwgb.conn = conn
	lwgb.logger.Info("本地War3游戏UDP广播监听启动成功", zap.String("address", address))

	defer func() {
		lwgb.conn.Close()
		lwgb.logger.Info("本地War3游戏UDP广播监听已关闭")
	}()

	buffer := make([]byte, 1024)
	for !lwgb.closed {
		n, addr, err := conn.ReadFrom(buffer)
		if err != nil {
			if lwgb.closed {
				return nil
			}
			lwgb.logger.Error("读取UDP数据失败", zap.Error(err))
			continue
		}

		// 只处理本地war3 game的udp包
		// 从addr中提取IP地址（去掉端口）
		var fromIP string
		if udpAddr, ok := addr.(*net.UDPAddr); ok {
			fromIP = udpAddr.IP.String()
		} else {
			fromIP = addr.String()
		}

		if fromIP == lwgb.client.GetWar3LocalIP().String() {
			lwgb.logger.Info("收到本地War3游戏UDP包",
				zap.String("from_addr", addr.String()),
				zap.Int("size", n))

			// 广播转发UDP包数据给所有远程客户端
			lwgb.broadcastToAllServers(buffer[:n])
		}
	}

	return nil
}

// Stop 停止广播监听
func (lwgb *LocalWar3GameBroadcast) Stop() {
	lwgb.closed = true
	if lwgb.conn != nil {
		lwgb.conn.Close()
	}
}

// broadcastToAllServers 广播数据到所有War3Server
func (lwgb *LocalWar3GameBroadcast) broadcastToAllServers(data []byte) {
	connectionServer := lwgb.client.GetConnectionServer()
	if connectionServer == nil {
		lwgb.logger.Error("连接服务器为空，无法转发数据")
		return
	}

	servers := lwgb.client.GetAllWar3Servers()
	for otherWar3IP := range servers {
		lwgb.logger.Debug("转发UDP数据到War3Server",
			zap.String("other_war3_ip", otherWar3IP),
			zap.Int("data_size", len(data)))

		if err := connectionServer.ForwardUdpDataToServer(otherWar3IP, data, len(data)); err != nil {
			lwgb.logger.Error("转发UDP数据失败",
				zap.String("other_war3_ip", otherWar3IP),
				zap.Error(err))
		}
	}
}
